Go grpc
Table of Contents
Section titled “Table of Contents”$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 # 添加环境变量 GOPATH $ export PATH="$PATH:$(go env GOPATH)/bin" $ echo $PATH | xargs -d ':' -n1 |grep go > /usr/local/go/bin # 确认已安装 $ protoc --version > libprotoc 3.20.3 $ protoc-gen-go --version > protoc-gen-go v1.28.1 $ protoc-gen-go-grpc --version > protoc-gen-go-grpc 1.2.0
grpc 是一个高性能、开源和通用的 RPC 框架,由 Google 团队开发,用于在分布式系统中进行 RPC 调用 使用 hello.proto 生成服务端和客户端代码
syntax = "proto3"; // 客户端指定 client/pb 作为包名 option go_package = "server/pb"; package pb; message HelloRequest { string name = 1; } message HelloResponse { string message = 1; } service Hello { rpc SayHello(HelloRequest) returns (HelloResponse) {} }
server ├── go.mod ├── go.sum ├── main.go └── pb ├── hello.pb.go ├── hello.proto └── hello_grpc.pb.go client ├── go.mod ├── go.sum ├── main.go └── pb ├── hello.pb.go ├── hello.proto └── hello_grpc.pb.go # 在服务端和客户端项目根目录执行命令, 按 protoc 生成源码 protoc --go_out=. --go_opt=paths=source_relative \ --go-grpc_out=. --go-grpc_opt=paths=source_relative \ pb/hello.proto
服务端代码 server/main.go
服务端安装 grpc 库 go get google.golang.org/grpc@latest
初始化服务端代码 go mod init server
package main import ( "fmt" "context" "net" "google.golang.org/grpc" // 引入 pb(protoc 生成的源码) "server/pb" ) // pb 的方法名称与 proto 文件中定义的 rpc 相关 type server struct { pb.UnimplementedHelloServer } func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) { fmt.Println("Received: ", in.GetName()) return &pb.HelloResponse{Message: "Hello " + in.GetName()}, nil } func main() { lis, err := net.Listen("tcp", ":50051") if err != nil { fmt.Println("failed to listen: ", err) } s := grpc.NewServer() pb.RegisterHelloServer(s, &server{}) fmt.Println("server listening at ", lis.Addr()) if err := s.Serve(lis); err != nil { fmt.Println("failed to serve: ", err) } }
package main import ( "context" "flag" "log" "time" "grpc_client/pb" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) const ( defaultName = "world" ) var ( // 50051 是服务端监听的端口 addr = flag.String("addr", "127.0.0.1:50051", "the address to connect to") name = flag.String("name", defaultName, "Name to greet") ) func main() { flag.Parse() // 连接到server端,此处禁用安全传输 conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := pb.NewHelloClient(conn) // 执行RPC调用并打印收到的响应数据 ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.SayHello(ctx, &pb.HelloRequest{Name: *name}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("Greeting: %s", r.GetMessage()) }
# 编译服务端和客户端代码 go build ./server ./client > 2024/04/06 19:12:17 Greeting: Hello world